home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / basic / UDP_Chat.lha / UDPChat / Old_Stuff / UDP_ChatV1.8.asc < prev    next >
Encoding:
Text File  |  1998-06-16  |  23.8 KB  |  744 lines

  1. ;
  2. ;                      UDP Chat code V1.8   8/2/98
  3. ;
  4. ;    This code sends and receives UDP data packets like a
  5. ;  a simple IRC client, and  checks wether they have arrived
  6. ;  at their destination.
  7. ;
  8. ;  Written by Anton Reinauer <anton@ww.co.nz>.
  9. ;  GUI: Alvaro Thompson <alvaro@enterprise.net> - And awful hacks
  10. ;  by me to his nice font sensitive code :-)
  11. ;        - typical bloody games programmer ;-)
  12. ;
  13. ;  Thanks to Paul Burkey for TCP_Funcs and to Dr. Ercole Spiteri
  14. ;  for TCP-to-Blitz.
  15. ;
  16. ;  Turn overflow errors off in Debugger options
  17.  
  18.  
  19. WBStartup
  20. NoCli
  21. Hostname.s="localhost"  ; default destination host address
  22. #PORT=3001              ; default destination port to send data to
  23. #LOCALPORT=3001
  24. #NO_CONNECTION=1        ; are we connected, or have we been connected to the Internet?
  25.                         ; 1 for not been connected, 0 for have/are connected.
  26. #MAX_NUMBER_PLAYERS=8
  27. GAME_NAME.s="UDP_Test"
  28.  
  29. INCLUDE "TCPFuncs.bb"
  30. INCLUDE "Net_Protocol_Header.bb2"  ; Net protocol constants
  31. DEFTYPE .w
  32.  
  33. packet_number.l=0
  34. online=0
  35. my_number=0
  36. last_message_number.l=0
  37. free_message.l=0
  38. ;********************************************************
  39.  
  40. NEWTYPE .message_status
  41.   number.l     ; packet number
  42.   ack.w        ; has it been received yet?
  43.   timestamp.l  ; when was it sent?
  44.   message.s    ; message
  45.   resends.w    ; how many times has it been re-sent?
  46.   player       ; which player was it sent too?
  47. End NEWTYPE
  48.  
  49. NEWTYPE .player_info
  50. status.w
  51. ascii_host_string.s
  52. player_colour.w
  53. score.l
  54. name.s
  55. nick.s
  56. End NEWTYPE
  57.  
  58. ;*******************************************************
  59. .Dims
  60.  
  61. Dim messages.message_status(100)
  62. Dim host.sockaddrin(8), hostlen.l(8)
  63. Dim players.player_info(8)
  64.  
  65. DEFTYPE .sockaddrin temphost
  66. ;*******************************************************
  67.  
  68. .Print_String
  69. Statement Print_String{text$}
  70.   SHARED ypos
  71.   If ypos<200
  72.     ypos+10
  73.   Else
  74.     WScroll 10,60,590,220,0,10
  75.   EndIf
  76.  
  77.   WLocate 10,ypos
  78.   Print text$               ; print string received
  79. End Function
  80.  
  81. .Get_Packet_Source
  82. Function.w Get_Packet_Source{}
  83.  SHARED host(),temphost
  84.  i=0
  85.  Repeat
  86.    i+1
  87.    If host(i)\sin_addr\s_addr=temphost\sin_addr\s_addr AND  host(i)\sin_port=temphost\sin_port
  88.      exit=1
  89.    EndIf
  90.    If i=8 AND exit=0
  91.      i=-1
  92.      exit=1
  93.    EndIf
  94.  Until  exit=1
  95.  
  96.  Function Return i
  97. End Function
  98.  
  99. .Get_Ascii_Address
  100. Function.s Get_Ascii_Address{address.l}
  101.   string_address.l=Inet_NtoA_(address) ; get memory address of ASCII string version of host address (a.b.c.d)
  102.   If string_address=0
  103.     Function Return ""
  104.   EndIf
  105.   Repeat                               ; build ASCII host string
  106.     letter.b=(Peek.b(string_address))
  107.     If letter<>0
  108.       temp$=temp$+Chr$(letter)
  109.     EndIf
  110.     string_address+1
  111.   Until letter=0
  112.   Function Return temp$
  113. End Function
  114.  
  115.  
  116. .WriteUDP
  117. Statement WriteUDP{ad.l,size.w,player}
  118.   SHARED sock.l,host(),hostlen(),temphost,temphostlen
  119.  
  120.   ; This routine writes data via UDP
  121.  
  122.   sockwrite.l=0                         ;Clear Writemask
  123.   sockwrite.l BitSet sock.l             ;set Writemask on our socket
  124.   g=WaitSelect_(2,0,&sockwrite.l,0,0,0) ;Wait until server is ready to read our data
  125.  
  126.   If player>0
  127.     c=sendto_(sock.l,ad,size,0,host(player),hostlen(player))    ;Send data to online host
  128.   Else
  129.     c=sendto_(sock.l,ad,size,0,temphost,temphostlen)            ;Send data to host that's not connected
  130.   EndIf
  131. End Statement
  132.  
  133. .Send_Reliable_Message
  134. Statement Send_Reliable_Message{send_string.s,player}
  135.  SHARED messages(),free_message,last_message_number,packet_number
  136.  
  137.   messages(free_message)\number=packet_number,False,Ticks,send_string.s,0,player
  138.   If messages(last_message_number)\ack=True
  139.     last_message_number=free_message
  140.   EndIf
  141.  
  142.   WriteUDP{&send_string.s,Len(send_string.s),player}
  143.   packet_number+1
  144.   free_message+1
  145.   If free_message=101 Then free_message=0
  146.  
  147. End Statement
  148.  
  149. .ReadUDP
  150. Function .s ReadUDP{}
  151.   SHARED sock.l,TCPmem.l,temphost,temphostlen
  152.  
  153.   ; This Function reads data from the socket it is bound to.
  154.   ; If there is no messages then it will return an empty string =""
  155.  
  156.   sockread.l=0                              ;Clear Readmask
  157.   sockread.l BitSet sock.l                  ;Set Readmask on our socket
  158.   e=IoctlSocket_(sock.l,#FIONREAD,TCPmem.l) ;How much data is there?
  159.   f.l=Peek.l(TCPmem.l)                      ;Place value in f
  160.  
  161.   If f>0                                    ; any data waiting
  162.     temphostlen=SizeOf .sockaddrin
  163.     c=recvfrom_(sock.l,TCPmem.l,f,0,temphost,temphostlen)  ;Read all data waiting on socket
  164.                                                            ;and get host it was sent from in temphost
  165.     If c>0    ; if there any data waiting
  166.         a=0 : c$=""
  167.         Repeat
  168.             c$=c$+Chr$(Peek.b(TCPmem+a)) : a+1    ; build string
  169.         Until a=c
  170.     EndIf
  171.  
  172.   EndIf
  173.  
  174.   Function Return c$
  175. End Function
  176.  
  177. .Get_Host_By_Name
  178. Function Get_Host_By_Name{host$,port.w,player}
  179.   SHARED host(),hostlen()
  180.  
  181.   *a.hostent=gethostbyname_(host$)     ; set up destination address to send packets to
  182.   If *a.hostent=0
  183.     WLocate 10,18
  184.     Print "    No connection to host           "
  185.     Function Return False
  186.   Else
  187.     WLocate 10,18
  188.     Print "Type in data, and hit return to send"
  189.   EndIf
  190.  
  191.   ;Copy Details to our Sockaddrin structure
  192.  
  193.   bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(player)\sin_addr,*a.hostent\h_length)
  194.  
  195.   host(player)\sin_port=port       ;Set port number
  196.   host(player)\sin_family=2        ;Set type to AT_INET
  197.   hostlen(player)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  198.  
  199.   Function Return True
  200. End Function
  201.  
  202. .Get_Host_By_Address
  203. Function.b Get_Host_By_Address{address.l,port,player}
  204.   SHARED host(),hostlen()
  205.  
  206.   *a.hostent=gethostbyaddr_(address,4,2)  ; check wether host exists- we're not being shammed
  207.  
  208.   If *a.hostent=0
  209.     Function Return False
  210.   EndIf
  211.  
  212.   bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(player)\sin_addr,*a.hostent\h_length) ; copy details to player's host
  213.                                                                                        ; newtype to host
  214.   host(player)\sin_port=port               ;Set port number
  215.   host(player)\sin_family=2                ;Set type to AT_INET
  216.   hostlen(player)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  217.   Function Return True
  218. End Function
  219.  
  220. .Localhost_Name
  221. Function.s Localhost_Name{}
  222.     If OpenFile (0,"ENV:HOSTNAME")
  223.        FileInput 0
  224.        While NOT Eof(0)
  225.          a$=a$+Inkey$
  226.        Wend
  227.        CloseFile 0
  228.        WindowInput 0
  229.        Function Return a$
  230.     EndIf
  231.     Function Return "localhost"
  232. End Function
  233.  
  234. .ConnectUDP
  235. Function ConnectUDP{host$,port.w}
  236.   SHARED sock.l,host(),hostlen(),port_used
  237.   ;
  238.   ; Open UDP socket and bind it to a port number
  239.   ; Return true or False if successful or not
  240.   ;
  241.  
  242.   lib.l=OpenLibrary_("bsdsocket.library",0)   ; check to see if a TCP/IP stack is running
  243.   If lib=0
  244.     Function Return False
  245.   Else
  246.     CloseLibrary_(lib)
  247.     sock.l=socket_(2,2,0)        ; open UDP socket
  248.     If sock=-1
  249.       Function Return False
  250.     Else
  251.         *a.hostent=gethostbyname_(host$)     ; set up destination address to send packets to
  252.         If *a.hostent=0
  253.            Function Return False
  254.         EndIf
  255.                                                                                                                     inY=WBHeight
  256.         ;Copy Details to our Sockaddrin structure
  257.  
  258.         bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(0)\sin_addr,*a.hostent\h_length)
  259.  
  260.         host(0)\sin_port=port       ;Set port number
  261.         host(0)\sin_family=2        ;Set type to AT_INET
  262.         hostlen(0)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  263.  
  264.         temp=0
  265.         port_used=port
  266.         Repeat
  267.           host(0)\sin_port=port_used  ; for testing on localhost- keep trying one port at a time after #LOCALPORT for
  268.           If bind_(sock,host(0),hostlen(0))=0    ; bind socket to port so we can                                     free port
  269.             Function Return True           ; receive data on port
  270.           Else
  271.             port_used+1
  272.             temp+1
  273.           EndIf
  274.         Until temp=10
  275.     EndIf
  276.   EndIf
  277. End Function
  278.  
  279. .Resend_Message
  280. Function Resend_Message{message_number}
  281.   SHARED messages()
  282.   messages(message_number)\timestamp=Ticks
  283.   messages(message_number)\resends+1
  284.   If messages(message_number)\resends>5  ; is host not responding?
  285.      Print_String{"Host not responding to Packet no: " + Str$(message_number)}
  286.      Function Return False
  287.   Else
  288.      WriteUDP{&messages(message_number)\message,Len(messages(message_number)\message),messages(message_number)\player}
  289.      Print_String{"Resent Packet no:" + Str$(message_number)}
  290.      Function Return True
  291.   EndIf
  292. End Statement
  293.  
  294. .Find_Next_Message
  295. Statement Find_Next_Message{}
  296. SHARED last_message_number,messages(),free_message
  297.  
  298.   exit=0
  299.   Repeat              ; find next unacknowledged message in array
  300.  
  301.     last_message_number+1
  302.     If last_message_number=101 Then last_message_number=0
  303.  
  304.     If last_message_number=free_message  ; if have got to free_message then there are no messages waiting to be acknowledged
  305.       If last_message_number=0
  306.         last_message_number=100
  307.         exit=1
  308.       Else
  309.         last_message_number-1
  310.         exit=1
  311.       EndIf
  312.     Else
  313.       If messages(last_message_number)\ack=False   ; we've found the next unacknowledged message in the array
  314.         exit=1
  315.       EndIf
  316.     EndIf
  317.  
  318.   Until exit=1
  319. End Statement
  320.  
  321. .Acknowledge_Packet   ; mark message as been sucessfully sent
  322. Statement Acknowledge_Packet{ack_packet_number}
  323.   SHARED last_message_number,free_message,messages()
  324.  
  325.   a=last_message_number
  326.   exit=0
  327.   Repeat
  328.     If messages(a)\number=ack_packet_number   ; find message in sent messages array
  329.       messages(a)\ack=True         ; note it as being received
  330.       Format "0000"
  331.       current_time.l=Ticks
  332.       current_lag=current_time-messages(a)\timestamp ; calculate lag
  333.       b$=Str$(current_lag)
  334.       WLocate 142,32
  335.       Print b$         ; print lag onscreen
  336.       Format""
  337.       exit=1
  338.     EndIf
  339.     a+1
  340.     If a=101 Then a=0    ; if at end of array, jump to beginning
  341.   Until exit=1
  342.  
  343.   If a=last_message_number+1 OR (a=0 AND last_message_number=100)   ; if last message unacknowledged is acknowledged
  344.     Find_Next_Message{}                                             ; then find next unacknowledged message
  345.   Else                ; we have lost a packet- resend last packet number!
  346.     If messages(last_message_number)\timestamp-current_time > current_lag+5    ; if its behind the current lag resend it
  347.       Print_String{"Received packet ACK out of order, resending last unacknowledged packet."}
  348.       If Resend_Message{last_message_number}= False   ; if run out of resends- time out message
  349.         messages(last_message_number)\timestamp=current_time+500  ; stop it resending the packet infinitely
  350.         Acknowledge_Packet{last_message_number}       ; wipe message off message acknowledge array
  351.       EndIf
  352.     EndIf
  353.   EndIf
  354. End Statement
  355.  
  356. .Requested_Connection
  357. Function.s Requested_Connection{incoming_string.s}
  358.   SHARED sock,players(),host(),hostlen(),GAME_NAME,CP_REP_ACCEPT.s,CP_REP_REJECT.s
  359.   SHARED send$,player,temphost,temphostlen,CP_REP_PLAYER_INFO.s
  360.   SHARED packet_number,online,my_number
  361.  
  362.   If online<2
  363.     dummy=3
  364.     Repeat            ; build game name string from incoming request
  365.       b$=Mid$(incoming_string,dummy,1)
  366.       If b$<>Chr$(0)
  367.         c$=c$+b$
  368.       EndIf
  369.       dummy+1
  370.     Until b$=Chr$(0) OR dummy=(Len(incoming_string))
  371.  
  372.     If b$=Chr$(0)
  373.       If c$=GAME_NAME.s            ; if request is for correct game
  374.         protocol=Asc(Right$(incoming_string,1))
  375.         If protocol=#NET_PROTOCOL_VERSION  ; check wether using the same protocol
  376.           a$="Connection request from "
  377.           player=1
  378.           exit=0
  379.           Repeat      ;check if a spare player slot is availiable
  380.             player+1
  381.             If players(player)\status=0
  382.               exit=1
  383.             Else
  384.               If player=8
  385.                 exit=1
  386.                 player=-1
  387.               EndIf
  388.             EndIf
  389.           Until exit=1
  390.  
  391.           If player>0     ; connection accepted
  392.             If Get_Host_By_Address{&temphost\sin_addr\s_addr,temphost\sin_port,player}=False
  393.               Function Return Str$(temphost\sin_addr\s_addr) + "- Host not found!"
  394.             EndIf
  395.  
  396.             players(player)\status=1
  397.             my_number=1
  398.             players(1)\status=1       ; We are now online as Server
  399.             If Get_Host_By_Address{&host(0)\sin_addr\s_addr,host(0)\sin_port,1}= False  ; put our details in Server Slot
  400.               Function Return Str$(host(0)\sin_addr\s_addr) + "- Host not found!"
  401.             EndIf
  402.  
  403.             temp$=Get_Ascii_Address{host(player)\sin_addr\s_addr}
  404.  
  405.             a$=a$+temp$ + "  Port: " + Str$(host(player)\sin_port)
  406.             players(player)\ascii_host_string=temp$   ; store it
  407.  
  408.             For i=1 To #MAX_NUMBER_PLAYERS
  409.               If i<> player AND players(i)\status=1
  410.                 If i>1
  411.                   ; build player info string
  412.                   send$=CP_REP_PLAYER_INFO.s + Mkl$(packet_number) + Mki$(player) + Mkl$(host(player)\sin_addr\s_addr)
  413.                   send$=send$ + Mki$(host(player)\sin_port) + Chr$(players(player)\player_colour)
  414.                   send$=send$ + Mkl$(players(player)\score)
  415.                   send$=send$ + players(player)\name + Chr$(0) + players(player)\nick
  416.  
  417.                   Send_Reliable_Message{send$,i}    ; tell others players that new player is online
  418.                                                     ; and give them new players info.
  419.                 EndIf
  420.  
  421.                 send$=CP_REP_PLAYER_INFO.s + Mkl$(packet_number) + Mki$(i) + Mkl$(host(i)\sin_addr\s_addr)
  422.                 send$=send$ + Mki$(host(i)\sin_port) + Chr$(players(i)\player_colour)
  423.                 send$=send$ + Mkl$(players(i)\score)
  424.                 send$=send$ + players(i)\name + Chr$(0) + players(i)\nick
  425.  
  426.                 Send_Reliable_Message{send$,player}    ; tell new player of others online
  427.                                                        ; and give them their info.
  428.               EndIf
  429.  
  430.             Next
  431.  
  432.  
  433.             send$=CP_REP_ACCEPT.s + Mkl$(packet_number)
  434.             send$=send$ + Mki$(host(0)\sin_port)+ Chr$(player) + Mki$(map)  ; send connection accepted back to client
  435.             online=1
  436.             Function Return a$
  437.           Else
  438.             a$=a$+"- no spare player slot!"
  439.           EndIf
  440.         Else
  441.           a$="Connection request- Incorrect Protocol: "+Str$(protocol)
  442.         EndIf
  443.       Else
  444.         a$="Wrong game name connection request: "+b$
  445.       EndIf
  446.     Else
  447.       a$="Connection request- Unknown error!"
  448.     EndIf
  449.   Else
  450.     a$="Connection Request rejected- host already logged on as Client"
  451.   EndIf
  452.  
  453.   send$=CP_REP_REJECT.s +  Mkl$(packet_number) + a$  ; send connection rejected back with reason
  454.   player=0                    ; send packet back to temphost
  455.   Function Return a$
  456. End Function
  457.  
  458. .Decode_Packet
  459. Statement Decode_Packet{incoming_string.s}
  460.   SHARED players(),host(),GAME_NAME.s,temphost,temphostlen,online,REL_PACKET_ACK.s,CP_REP_ACCEPT.s
  461.   SHARED send$,player,my_number
  462.   packet_type=Asc(Left$(incoming_string,1))
  463.   packet_not_connected=0   ; check to see if packet should be from reliable online source
  464.   player=Get_Packet_Source{}  ; check to see if packet is from reliable online source
  465.   return_message=0
  466.  
  467.   Select packet_type
  468.     Case  #CONTROL_PACKET
  469.       packet_type=Asc(Mid$(incoming_string,2))
  470.       Select packet_type
  471.         Case #CP_REQ_CONNECT      ; request to login to Server
  472.           a$=Requested_Connection{incoming_string}
  473.           packet_not_connected=1
  474.           return_message=2
  475.         Case #CP_REP_ACCEPT       ; We Received confirmation of logon from Server
  476.           online=2
  477.           packet_number.l=Cvl(Mid$(incoming_string,3,4))
  478.           my_number=Val(Mid$(incoming_string,9,1))
  479.           map.w=Cvi(Mid$(incoming_string,10,2))
  480.           players(1)\status=1
  481.           a$="Connection Accepted"
  482.           return_message=3
  483.         Case #CP_REP_REJECT       ; Our logon request was rejected by host
  484.           packet_number.l=Cvl(Mid$(incoming_string,3,4))
  485.           a$=Mid$(incoming_string,7)
  486.           return_message=3
  487.         Case #CP_REP_PLAYER_INFO  ; Information about new player that has just logged on
  488.           newplayer=Cvi(Mid$(incoming_string,7,2))
  489.           packet_number.l=Cvl(Mid$(incoming_string,3,4))
  490.           address.l=Cvl(Mid$(incoming_string,9,4))
  491.           If Get_Host_By_Address{&address,Cvi(Mid$(incoming_string,13,2)),newplayer}=True
  492.             ascii_address.s=Get_Ascii_Address{address}
  493.             players(newplayer)\status=1,ascii_address.s
  494.             players(newplayer)\player_colour=Val(Mid$(incoming_string,15,1))
  495.             players(newplayer)\score=Cvi(Mid$(incoming_string,16,4))
  496.             a$="New player at- " + ascii_address.s + " Port: " + Str$(host(newplayer)\sin_port)
  497.           Else
  498.             a$="New player at unknown host!"
  499.           EndIf
  500.           return_message=3
  501.        End Select
  502.  
  503.     Case #REL_STRING_END
  504.       packet_number.l=Cvl(Mid$(incoming_string,2,4))
  505.       a$=Str$(packet_number) + "," + Str$(player)  + ": " + Mid$(incoming_string,6,Len(incoming_string)-6)
  506.       return_message=3
  507.  
  508.     Case #REL_PACKET_ACK
  509.       packet_number.l=Cvl(Mid$(incoming_string,2,4))
  510.       a$=": Packet no. " + Str$(packet_number) + " arrived at destination."
  511.       Acknowledge_Packet{packet_number}
  512.  
  513.     Default                        ; unknown packet type received
  514.       If player<0                  ; if from unknown source
  515.         temp$=Get_Ascii_Address{temphost\sin_addr\s_addr} + "Port: " + Str$(temphost\sin_port)
  516.       Else                         ; from known source
  517.         temp$="Player: " + Str$(player)
  518.       EndIf
  519.       a$="Unknown Packet from: " + temp$
  520.   End Select
  521.  
  522.   If player<0 AND packet_not_connected=0
  523.     Print_String{"Warning: Packet from unknown source!"}
  524.     Statement Return
  525.   EndIf
  526.  
  527.   If return_message>0
  528.     If return_message=2
  529.       Send_Reliable_Message{send$,player}  ; send packet back (return_message=2)
  530.     Else
  531.       If return_message=3  ; send packet acknowledgment back
  532.         send$=REL_PACKET_ACK.s + Mkl$(packet_number)
  533.       EndIf
  534.       WriteUDP{&send$,Len(send$),player}  ; return_message= 1 or 3
  535.     EndIf
  536.   EndIf
  537.  
  538.   a$="R "+a$
  539.   Print_String{a$}
  540. End Statement
  541.  
  542. ;****************************************
  543.  
  544.  
  545. Gosub Init_Gui
  546.  
  547. ypos=40
  548. xpos=10
  549. messages(free_message)\ack=True
  550.  
  551. CNIF #NO_CONNECTION=1    ; if not connected to the `net
  552.  
  553.   If ConnectUDP {Hostname,#LOCALPORT}              ; bind socket to local port
  554.      Print_String {"Bound to "+Hostname+" "+ Str$(port_used)}
  555.      WLocate 510,4
  556.      Print "Bound to: ",port_used
  557.   Else
  558.      Print_String { "Error in setting up UDP at Port "+ Str$(port_used)}
  559.      Goto Exit
  560.   EndIf
  561.  
  562.   If Get_Host_By_Name {Hostname,#PORT,0}  :EndIf
  563.  
  564. CELSE
  565.   If ConnectUDP {Localhost_Name{},#LOCALPORT}              ; bind socket to local port
  566.      Print_String {"Bound to "+Hostname+" "+ Str$(port_used)}
  567.      WLocate 510,4
  568.      Print "Bound to: ",port_used
  569.   Else
  570.      Print_String { "Error in setting up UDP at Port "+ Str$(port_used)}
  571.      Goto Exit
  572.   EndIf
  573.  
  574.   If Get_Host_By_Name {Localhost_Name{},#PORT,0}  :EndIf
  575. CEND
  576.  
  577. ResetTimer
  578.  
  579. ;****************************************
  580.  
  581. .Main
  582.  
  583. Repeat
  584.  
  585.     VWait
  586.  
  587.     If ev.l=$40
  588.       Select GadgetHit
  589.         Case51           ; Server to connect to
  590.           If online=0
  591.             If Get_Host_By_Name{GTGetString(0,51), GTGetInteger(0,52),1}=True
  592.               Print_String{"Attempting to connect to Server"}
  593.               send$=CP_REQ_CONNECT.s+GAME_NAME.s+Chr$(0)+NET_PROTOCOL_VERSION.s
  594.               WriteUDP{&send$,Len(send$),1}
  595.             EndIf
  596.           Else
  597.             If online=2
  598.               Print_String{"Already logged on to a Server!"}
  599.             Else
  600.               Print_String{"Already acting as a Server!"}
  601.             EndIf
  602.           EndIf
  603.         Case52           ; Port to connect at above Server
  604.           If Get_Host_By_Name{GTGetString(0,51), GTGetInteger(0,52),1} :EndIf
  605.         Case53           ; Delay 1s
  606.           VWait 50
  607.         Case54           ; get name of localhost
  608.           a$=Localhost_Name {}   ;
  609.           WLocate 315+pingwidth+15,hostnamey+3
  610.           Print a$
  611.         Case63       ; Delay 5s
  612.           VWait 2000   ; delay 40s
  613.         Case64         ; Send message to connected players
  614.          If online>0
  615.              temp$=GTGetString(0,64)
  616.              For i=1 To 8
  617.                If players(i)\status=1  AND i<>my_number
  618.                  Print_String{"S " + Str$(packet_number) + "," + Str$(i)  + ": "+ temp$}
  619.                  send$=REL_STRING_END.s + Mkl$(packet_number) + temp$ + Chr$(0)
  620.                  Send_Reliable_Message{send$,i}   ; Send string to connected players
  621.                EndIf
  622.              Next
  623.          EndIf
  624.        End Select
  625.     EndIf
  626.  
  627.     a$=ReadUDP{}   ; get data from socket
  628.  
  629.     If a$<>""
  630.        Decode_Packet{a$}
  631.     EndIf
  632.  
  633.     If messages(last_message_number)\ack=False  ; only check if there's messages that haven't been acknowledged yet.
  634.       If Ticks>messages(last_message_number)\timestamp+250  ; has it been 5 secs since the packet was sent?
  635.         If Resend_Message{last_message_number}= False   ; if run out of resends- time out message
  636.           Acknowledge_Packet{message_number}            ; wipe message off message acknowledge array
  637.         EndIf
  638.       EndIf
  639.     EndIf
  640.  
  641.     ev=Event
  642.  
  643. Until ev=$200    ; shut down if close gadget hit
  644.  
  645. CloseTCP{}                          ; close connection
  646.  
  647. Exit:
  648. WLocate 10,18
  649. Print "                                    "
  650. WLocate 10,18
  651. Print"Socket closed"
  652. Delay_(30)
  653.  
  654. FreeMem TCPmem,$2000
  655.  
  656. End
  657.  
  658. ;****************************************
  659.  
  660. .Init_Gui
  661.     WBenchToFront_
  662.     WbToScreen0
  663.     DefaultIDCMP $20|$40|$200
  664.     *scr.Screen=Peek.l(Addr Screen(0))
  665.     *myfont.TextAttr=*scr\Font
  666.     fontheight=*myfont\ta_YSize
  667.     ad1.l=*myfont\ta_Name
  668.     fontname$=Peek$(ad1)
  669.  
  670.     LoadFont 1,fontname$,fontheight,0
  671.  
  672.     portwidth=TextLength_(*scr\_RastPort,"Port:",5)+10
  673.     numberswidth=TextLength_(*scr\_RastPort,"99999",5)+14
  674.     serverwidth=TextLength_(*scr\_RastPort,"Send To:",8)+10
  675.     connectwidth=TextLength_(*scr\_RastPort,"Connect",7)+14
  676.     disconnectwidth=TextLength_(*scr\_RastPort,"Disconnect",10)+14
  677.     pingwidth=TextLength_(*scr\_RastPort,"Localhost:",11)
  678.     delaywidth=TextLength_(*scr\_RastPort,"Delay 1s",8)+10
  679.     inputwidth=TextLength_(*scr\_RastPort,"Input:",6)+10
  680.     firstperson=TextLength_(*scr\_RastPort,"1:",2)+10
  681.  
  682.     #SERVERBTN       =51
  683.     #PORTBTN         =52
  684.     #BUTTON          =53
  685.  
  686.     x=1
  687.     y=1
  688.  
  689.     x1=x+(serverwidth*3)+portwidth+numberswidth+9+3+connectwidth+5
  690.  
  691.     If #NO_CONNECTION=0
  692.       GTString  0,#SERVERBTN,x+serverwidth,y,serverwidth*2,fontheight+4,"Send To:",1,256,Localhost_Name {}
  693.     Else
  694.       GTString  0,#SERVERBTN,x+serverwidth,y,serverwidth*2,fontheight+4,"Send To:",1,256,"localhost"
  695.     EndIf
  696.     GTInteger 0,#PORTBTN,x+(serverwidth*3)+portwidth+3,y,numberswidth,fontheight+4,"Port:",1,#PORT
  697.     GTButton  0,#BUTTON,345,y,delaywidth,fontheight+4,"Delay 1s",$10
  698.     GTButton  0,63,340+delaywidth+10,y,delaywidth,fontheight+4,"Delay 5s",$10
  699.     y+fontheight+5
  700.  
  701.     hostnamey=y
  702.  
  703.     GTButton  0,54,315,y,pingwidth,fontheight+4,"Localhost:",$10
  704.  
  705.     WinWidth=x+(serverwidth*3)+portwidth+numberswidth+9+3+connectwidth+8+disconnectwidth+8+90
  706.  
  707.     y+fontheight+5
  708.  
  709.     GTButton  0,55,120,y,firstperson,fontheight+4,"1:",$10
  710.     GTButton  0,56,180,y,firstperson,fontheight+4,"2:",$10
  711.     GTButton  0,57,240,y,firstperson,fontheight+4,"3:",$10
  712.     GTButton  0,58,300,y,firstperson,fontheight+4,"4:",$10
  713.     GTButton  0,59,360,y,firstperson,fontheight+4,"5:",$10
  714.     GTButton  0,60,420,y,firstperson,fontheight+4,"6:",$10
  715.     GTButton  0,61,480,y,firstperson,fontheight+4,"7:",$10
  716.     GTButton  0,62,540,y,firstperson,fontheight+4,"8:",$10
  717.  
  718.     GTString  0,64,50,215,550,fontheight+4,"Send:",1,67,""
  719.  
  720.     WinHeight=y+fontheight+5
  721.  
  722.     ;WinX=WBWidth/2-(WinWidth/2)
  723.     ;WinY=WBHeight/2-(WinHeight/2)
  724.  
  725.     WinTitle$="UDP Chat"
  726.     ;ScreenTitle$="UDP Send "+Chr$(169)+"1997."
  727.  
  728.     Window 0,0,10,WinWidth,245,$0002|$0004|$0008,WinTitle$,1,2
  729.     Use Window 0:Activate 0:AttachGTList 0,0:WTitle WinTitle$,ScreenTitle$:Menus Off
  730.  
  731.     WindowOutput0
  732.     WindowInput 0
  733.  
  734.     a$=Localhost_Name {}   ;
  735.     WLocate 315+pingwidth+15,hostnamey+3
  736.     Print a$
  737.  
  738.     WLocate 10,y+3
  739.     Print"Ping Time-VBL"
  740.  
  741. Return
  742.  
  743.  
  744.